// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包io为I/O原语提供基本接口。
// 它的主要工作是将这些原语的现有实现，如包操作系统中的实现，封装到共享的公共接口中，这些接口抽象了功能，以及其他一些相关的原语。
// 
// 因为这些接口和原语用
// 各种实现包装了较低级别的操作，除非另有通知，否则客户端不应假定它们可以安全地并行执行。
package io

import (
	"errors"
	"sync"
)

// 寻找从何而来的值。
const (
	SeekStart   = 0 // seek相对于文件的源
	SeekCurrent = 1 // seek相对于当前偏移量
	SeekEnd     = 2 // seek相对于结束
)

// ErrShortWrite意味着写入接受的字节数少于请求的
// ，但未能返回显式错误。
var ErrShortWrite = errors.New("short write")

// errInvalidWrite表示写入操作返回一个不可能的计数。
var errInvalidWrite = errors.New("invalid write result")

// ErrShortBuffer表示读取所需的缓冲区比提供的缓冲区长。
var ErrShortBuffer = errors.New("short buffer")

// EOF是当没有更多可用输入时，Read返回的错误。
// （Read必须返回EOF本身，而不是包装EOF的错误，因为调用方将使用==）测试EOF。）
// 函数应该只返回EOF，以表示输入结束。
// 如果EOF在结构化数据流中意外发生，
// 相应的错误可能是errunexpectedof或其他一些错误
// 提供更多详细信息。
var EOF = errors.New("EOF")

// errunexpectedof表示在读取固定大小的块或数据结构的过程中遇到EOF。
var ErrUnexpectedEOF = errors.New("unexpected EOF")

// 当
// 许多读取调用都未能返回任何数据或错误时，读卡器的一些客户端会返回ErrNoProgress，
// 通常是读卡器实现中断的标志。
var ErrNoProgress = errors.New("multiple Read calls return no data or error")

// Reader是封装基本读取方法的接口。
// 
// Read最多可将len（p）字节读入p。它返回字节数
// Read（0<=n<=len（p））和遇到的任何错误。即使Read 
// 返回n<len（p），它也可能在调用期间使用所有p作为暂存空间。
// 如果某些数据可用，但不是len（p）字节，则按常规读取
// 返回可用数据，而不是等待更多数据。
// 
// 在
// 成功读取n>0字节后，当Read遇到错误或文件结束条件时，返回
// 读取的字节数。它可能会从同一个调用返回（非nil）错误
// 或从后续调用返回错误（n==0）。
// 这种一般情况的一个例子是，返回
// 输入流末尾非零字节数的读取器可能返回err==EOF或err==nil。下一次读取应该
// 返回0，EOF。
// 
// 考虑到错误错误，调用方应始终处理在
// 之前返回的n>0字节。这样做可以正确处理读取某些字节后发生的I/O错误
// 以及两个
// 允许的EOF行为。
// 
// 不鼓励Read的实现返回带有零错误的
// 零字节计数，除非len（p）==0。
// 呼叫者应将返回值0和零视为表示
// 未发生任何事情；特别是，它不表示EOF。
// 
// 实现不能保留p。
type Reader interface {
	Read(p []byte) (n int, err error)
}

// Writer是封装基本写入方法的接口。
// 
// 将len（p）字节从p写入底层数据流。
// 返回从p（0<=n<=len（p））写入的字节数
// 以及任何导致写入提前停止的错误。
// 如果Write返回n<len（p），则必须返回非nil错误。
// Write不能修改切片数据，即使是暂时的。
// 
// 实现不能保留p。
type Writer interface {
	Write(p []byte) (n int, err error)
}

// Closer是封装基本Close方法的接口。
// 
// 第一次调用后关闭的行为未定义。
// 特定的实现可能会记录自己的行为。
type Closer interface {
	Close() error
}

// Seek是封装基本搜索方法的接口。
// 
// Seek设置下一次读取或写入偏移量的偏移量，
// 根据位置进行解释：
// SeekStart表示相对于文件开头，
// SeekCurrent表示相对于当前偏移量，而
// SeekEnd表示相对于文件结尾。
// Seek返回相对于
// 文件开头的新偏移量或错误（如果有）。
// 
// 在文件开始之前寻找偏移量是错误的。
// 可能允许寻找任何正偏移量，但如果新偏移量超过
// 基础对象的大小，则后续I/O操作的行为
// 取决于实现。
type Seeker interface {
	Seek(offset int64, whence int) (int64, error)
}

// ReadWriter是对基本读写方法进行分组的接口。
type ReadWriter interface {
	Reader
	Writer
}

// ReadCloser是对基本读取和关闭方法进行分组的接口。
type ReadCloser interface {
	Reader
	Closer
}

// WriteCloser是对基本写入和关闭方法进行分组的接口。
type WriteCloser interface {
	Writer
	Closer
}

// ReadWriteCloser是对基本的读、写和关闭方法进行分组的接口。
type ReadWriteCloser interface {
	Reader
	Writer
	Closer
}

// ReadSeek是一个将基本读取和查找方法分组的接口。
type ReadSeeker interface {
	Reader
	Seeker
}

// ReadSeekCloser是对基本的读取、查找和关闭
// 方法进行分组的接口。
type ReadSeekCloser interface {
	Reader
	Seeker
	Closer
}

// WriteSeeker是对基本写入和查找方法进行分组的接口。
type WriteSeeker interface {
	Writer
	Seeker
}

// ReadWriteSeeker是一个将基本读、写和查找方法分组的接口。
type ReadWriteSeeker interface {
	Reader
	Writer
	Seeker
}

// ReaderFrom是封装ReadFrom方法的接口。
// 
// ReadFrom从r读取数据，直到EOF或错误。
// 返回值n是读取的字节数。
// 读取过程中遇到的除EOF以外的任何错误也将返回。
// 
// 复制函数使用ReaderFrom（如果可用）。
type ReaderFrom interface {
	ReadFrom(r Reader) (n int64, err error)
}

// WriteTo是封装WriteTo方法的接口。
// 
// WriteTo将数据写入w，直到没有更多数据可写入，或
// 当发生错误时。返回值n是
// 写入的字节数。写入过程中遇到的任何错误也会返回。
// 
// 复制函数使用WriterTo（如果可用）。
type WriterTo interface {
	WriteTo(w Writer) (n int64, err error)
}

// ReaderAt是封装基本ReadAt方法的接口。
// 
// ReadAt从
// 基础输入源的偏移量开始，将len（p）字节读入p。它返回字节数
// read（0<=n<=len（p））和遇到的任何错误。
// 
// 当ReadAt返回n<len（p）时，它返回一个非零错误
// 解释为什么没有返回更多字节。在这方面，
// ReadAt比Read更严格。
// 
// 即使ReadAt返回n<len（p），它也可以在调用期间将所有p用作scratch 
// 空格。如果有一些数据可用，但没有len（p）字节，则
// ReadAt将阻塞，直到所有数据可用或出现错误。
// 在这方面，ReadAt与Read不同。
// 
// 如果ReadAt返回的n=len（p）字节位于
// 输入源的末尾，ReadAt可能返回err==EOF或err==nil。
// 
// 如果ReadAt正在使用寻道偏移量从输入源读取数据，则
// ReadAt不应影响或受基础
// 寻道偏移量的影响。ReadAt的客户端可以在同一输入源上执行并行ReadAt调用。
// 
// 实现不能保留p。
type ReaderAt interface {
	ReadAt(p []byte, off int64) (n int, err error)
}

// WriterAt是封装基本WriteAt方法的接口。
// 
// WriteAt将len（p）字节从p写入基础数据流
// offset off。它返回从p（0<=n<=len（p））
// 写入的字节数，以及任何导致写入提前停止的错误。
// WriteAt如果返回n<len（p），则必须返回非nil错误。
// 
// 如果WriteAt正在使用寻道偏移量写入目标，
// WriteAt不应影响或受基础
// 寻道偏移量的影响。
// 
// 如果范围不重叠，WriteAt的客户端可以在同一个
// 目标上执行并行WriteAt调用。
// 
// 实现不能保留p。
type WriterAt interface {
	WriteAt(p []byte, off int64) (n int, err error)
}

// 字节阅读器是包装ReadByte方法的接口。
// 
// ReadByte读取并返回输入的下一个字节或
// 遇到的任何错误。如果ReadByte返回错误，则无输入
// 字节被消耗，返回的字节值未定义。
// 
// ReadByte在处理时为字节提供了一个高效的接口。未实现ByteReader 
// 的读卡器可以使用bufio进行包装。NewReader添加此方法。
type ByteReader interface {
	ReadByte() (byte, error)
}

// 字节扫描程序是将UnreadByte方法添加到
// 基本ReadByte方法的接口。
// 
// UnreadByte导致对ReadByte的下一次调用返回上次读取的字节。
// 如果最后一个操作没有成功调用ReadByte，UnreadByte可能返回一个错误，未读最后一个读取的字节（或在
// 最后一个未读字节之前的字节），或者（在支持Seeker接口的实现中）
// 查找到当前偏移量之前的一个字节。
type ByteScanner interface {
	ByteReader
	UnreadByte() error
}

// 字节编写器是封装WriteByte方法的接口。
type ByteWriter interface {
	WriteByte(c byte) error
}

// RuneReader是封装ReadRune方法的接口。
// 
// ReadRune读取单个编码的Unicode字符
// 并以字节为单位返回rune及其大小。如果没有字符
// 可用，将设置err。
type RuneReader interface {
	ReadRune() (r rune, size int, err error)
}

// RuneScanner是将UnreadRune方法添加到
// 基本ReadRune方法的接口。
// 
// UnreadRune导致下一次对ReadRune的调用返回上一次读取的符文。
// 如果最后一次操作没有成功调用ReadRune，UnreadRune可能返回一个错误，未读最后一次rune read（或在
// 最后一次未读rune之前的rune），或者（在支持Seeker接口的实现中）
// 在当前偏移量之前寻找rune的开始。
type RuneScanner interface {
	RuneReader
	UnreadRune() error
}

// StringWriter是包装WriteString方法的接口。
type StringWriter interface {
	WriteString(s string) (n int, err error)
}

// WriteString将字符串s的内容写入w，w接受字节片。
// 如果w实现了StringWriter，则直接调用其WriteString方法。
// 否则，w.Write只调用一次。
func WriteString(w Writer, s string) (n int, err error) {
	if sw, ok := w.(StringWriter); ok {
		return sw.WriteString(s)
	}
	return w.Write([]byte(s))
}

// 读取至少从r读取buf，直到读取至少最小字节。
// 它返回复制的字节数，如果读取的字节数较少，则返回一个错误。
// 仅当未读取字节时，错误为EOF。
// 如果在读取少于min字节后发生EOF，则
// readAtlast返回errunexpectedof。
// 如果min大于buf的长度，则READATLAST返回ErrShortBuffer。
// 返回时，n>=min当且仅当err==nil时。
// 如果r返回读取至少min字节的错误，则会删除该错误。
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) {
	if len(buf) < min {
		return 0, ErrShortBuffer
	}
	for n < min && err == nil {
		var nn int
		nn, err = r.Read(buf[n:])
		n += nn
	}
	if n >= min {
		err = nil
	} else if n > 0 && err == EOF {
		err = ErrUnexpectedEOF
	}
	return
}

// ReadFull将从r到buf的len（buf）字节精确读取。
// 它返回复制的字节数，如果读取的字节数较少，则返回一个错误。
// 仅当未读取字节时，错误为EOF。
// 如果在读取部分但不是全部字节后发生EOF，
// ReadFull返回errunexpectedof。
// 返回时，n==len（buf）当且仅当err==nil。
// 如果r返回读取至少len（buf）字节的错误，则会删除该错误。
func ReadFull(r Reader, buf []byte) (n int, err error) {
	return ReadAtLeast(r, buf, len(buf))
}

// CopyN将n个字节（或直到出现错误）从src复制到dst。
// 返回复制的字节数和最早的
// 复制时遇到的错误。
// 返回时，writed==n当且仅当err==nil。
// 
// 如果dst实现ReaderFrom接口，则
// 使用它实现副本。
func CopyN(dst Writer, src Reader, n int64) (written int64, err error) {
	written, err = Copy(dst, LimitReader(src, n))
	if written == n {
		return n, nil
	}
	if written < n && err == nil {
		// src提前停止；一定是EOF。
		err = EOF
	}
	return
}

// 将副本从src复制到dst，直到src上达到EOF或出现错误。它返回复制的字节数
// 以及复制时遇到的第一个错误（如果有）。
// 
// 成功的复制返回err==nil，而不是err==EOF。
// 因为Copy被定义为从src读取直到EOF，所以它不将EOF from read视为要报告的错误。
// 
// 如果src实现WriterTo接口，则
// 通过调用src实现复制。写入（dst）。
// 否则，如果dst实现ReaderFrom接口，则
// 通过调用dst实现拷贝。读自（src）。
func Copy(dst Writer, src Reader) (written int64, err error) {
	return copyBuffer(dst, src, nil)
}

// CopyBuffer与Copy相同，只是它通过
// 提供的缓冲区（如果需要）进行分级，而不是分配一个
// 临时缓冲区。如果buf为零，则分配一个；否则，如果它的
// 长度为零，则CopyBuffer会出现恐慌。
// 
// 如果src实现WriterTo或dst实现ReaderFrom，
// buf将不用于执行复制。
func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
	if buf != nil && len(buf) == 0 {
		panic("empty buffer in CopyBuffer")
	}
	return copyBuffer(dst, src, buf)
}

// copyBuffer是Copy和copyBuffer的实际实现。
// 如果buf为零，则分配一个。
func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
	// 如果读卡器有WriteTo方法，请使用它进行复制。
	// 避免分配和复制。
	if wt, ok := src.(WriterTo); ok {
		return wt.WriteTo(dst)
	}
	// 类似地，如果编写器有ReadFrom方法，请使用它进行复制。
	if rt, ok := dst.(ReaderFrom); ok {
		return rt.ReadFrom(src)
	}
	if buf == nil {
		size := 32 * 1024
		if l, ok := src.(*LimitedReader); ok && int64(size) > l.N {
			if l.N < 1 {
				size = 1
			} else {
				size = int(l.N)
			}
		}
		buf = make([]byte, size)
	}
	for {
		nr, er := src.Read(buf)
		if nr > 0 {
			nw, ew := dst.Write(buf[0:nr])
			if nw < 0 || nr < nw {
				nw = 0
				if ew == nil {
					ew = errInvalidWrite
				}
			}
			written += int64(nw)
			if ew != nil {
				err = ew
				break
			}
			if nr != nw {
				err = ErrShortWrite
				break
			}
		}
		if er != nil {
			if er != EOF {
				err = er
			}
			break
		}
	}
	return written, err
}

// LimitReader返回一个读卡器，该读卡器从r 
// 读取数据，但在n字节后以EOF停止。
// 底层实现是一个*LimitedReader。
func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} }

// LimitedReader从R读取数据，但将返回的数据量限制为仅N字节。每次读取
// 都会更新N以反映新的剩余金额。
// 当N<=0或基础R返回EOF时，Read返回EOF。
type LimitedReader struct {
	R Reader // 基础读卡器
	N int64  // 剩余最大字节数
}

func (l *LimitedReader) Read(p []byte) (n int, err error) {
	if l.N <= 0 {
		return 0, EOF
	}
	if int64(len(p)) > l.N {
		p = p[0:l.N]
	}
	n, err = l.R.Read(p)
	l.N -= int64(n)
	return
}

// NewsSectionReader返回一个从r 
// 读取的节读卡器，从偏移量off开始，在n字节后以EOF停止。
func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader {
	var remaining int64
	const maxint64 = 1<<63 - 1
	if off <= maxint64-n {
		remaining = n + off
	} else {
		// 溢出，无法返回错误。
		// 假设我们可以读取1<<63-1的偏移量。
		remaining = maxint64
	}
	return &SectionReader{r, off, off, remaining}
}

// SectionReader在底层Reader的一个节
// 上实现读取、查找和读取。
type SectionReader struct {
	r     ReaderAt
	base  int64
	off   int64
	limit int64
}

func (s *SectionReader) Read(p []byte) (n int, err error) {
	if s.off >= s.limit {
		return 0, EOF
	}
	if max := s.limit - s.off; int64(len(p)) > max {
		p = p[0:max]
	}
	n, err = s.r.ReadAt(p, s.off)
	s.off += int64(n)
	return
}

var errWhence = errors.New("Seek: invalid whence")
var errOffset = errors.New("Seek: invalid offset")

func (s *SectionReader) Seek(offset int64, whence int) (int64, error) {
	switch whence {
	default:
		return 0, errWhence
	case SeekStart:
		offset += s.base
	case SeekCurrent:
		offset += s.off
	case SeekEnd:
		offset += s.limit
	}
	if offset < s.base {
		return 0, errOffset
	}
	s.off = offset
	return offset - s.base, nil
}

func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) {
	if off < 0 || off >= s.limit-s.base {
		return 0, EOF
	}
	off += s.base
	if max := s.limit - off; int64(len(p)) > max {
		p = p[0:max]
		n, err = s.r.ReadAt(p, off)
		if err == nil {
			err = EOF
		}
		return n, err
	}
	return s.r.ReadAt(p, off)
}

// Size返回节的大小（字节）。
func (s *SectionReader) Size() int64 { return s.limit - s.base }

// TeeReader返回一个读卡器，该读卡器将从r读取的内容写入w。
// 通过它执行的从r读取的所有内容都与
// 对w的相应写入匹配。没有内部缓冲-
// 必须在读取完成之前完成写入。
// 写入时遇到的任何错误都将报告为读取错误。
func TeeReader(r Reader, w Writer) Reader {
	return &teeReader{r, w}
}

type teeReader struct {
	r Reader
	w Writer
}

func (t *teeReader) Read(p []byte) (n int, err error) {
	n, err = t.r.Read(p)
	if n > 0 {
		if n, err := t.w.Write(p[:n]); err != nil {
			return n, err
		}
	}
	return
}

// Discard是一个Writer，在该Writer上，所有Write调用都会在不做任何操作的情况下成功。
var Discard Writer = discard{}

type discard struct{}

// 放弃将ReaderFrom作为优化实现，因此复制到
// io。丢弃可以避免做不必要的工作。
var _ ReaderFrom = discard{}

func (discard) Write(p []byte) (int, error) {
	return len(p), nil
}

func (discard) WriteString(s string) (int, error) {
	return len(s), nil
}

var blackHolePool = sync.Pool{
	New: func() any {
		b := make([]byte, 8192)
		return &b
	},
}

func (discard) ReadFrom(r Reader) (n int64, err error) {
	bufp := blackHolePool.Get().(*[]byte)
	readSize := 0
	for {
		readSize, err = r.Read(*bufp)
		n += int64(readSize)
		if err != nil {
			blackHolePool.Put(bufp)
			if err == EOF {
				return n, nil
			}
			return
		}
	}
}

// NoCloser返回一个ReadCloser，其中包含一个无操作关闭方法包装
// 提供的读取器r。
func NopCloser(r Reader) ReadCloser {
	return nopCloser{r}
}

type nopCloser struct {
	Reader
}

func (nopCloser) Close() error { return nil }

// ReadAll从r读取，直到出现错误或EOF，并返回它读取的数据。
// 成功的调用返回err==nil，而不是err==EOF。因为ReadAll是
// 定义为从src读取直到EOF，所以它不会将读取
// 的EOF视为要报告的错误。
func ReadAll(r Reader) ([]byte, error) {
	b := make([]byte, 0, 512)
	for {
		if len(b) == cap(b) {
			// 添加更多容量（让append选择容量大小）。
			b = append(b, 0)[:len(b)]
		}
		n, err := r.Read(b[len(b):cap(b)])
		b = b[:len(b)+n]
		if err != nil {
			if err == EOF {
				err = nil
			}
			return b, err
		}
	}
}
